package com.abigdreamer.swing.app.skin;

import com.abigdreamer.io.FileUtil;
import com.abigdreamer.swing.component.UIUtil;
import com.sun.awt.AWTUtilities;
import craky.componentc.CRootPaneUI;
import craky.componentc.CRootPaneUI.ImageDisplayMode;
import craky.componentc.JCDialog;
import craky.componentc.JCFrame;
import craky.componentc.JCMessageBox;
import craky.componentc.JCSlider;
import craky.componentc.JCToggleButton;
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.ButtonModel;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.filechooser.FileNameExtensionFilter;

public class SkinMgr
  implements MouseListener, ChangeListener, ActionListener, PopupMenuListener
{
  private SkinMenu menu;
  private File currentDir;
  
  public SkinMgr(SkinMenu menu)
  {
    this.menu = menu;
  }
  
  public void removeSkin(Skin skin, boolean showConfirm)
  {
    if (skin != null) {
      if (showConfirm)
      {
        this.menu.showPane(false, skin);
      }
      else
      {
        String name = skin.getName();
        String current = SkinManager.getCurrentSkin().getName();
        SkinManager.getAllSkins().remove(name.toUpperCase());
        this.menu.resetSkins();
        SkinManager.changeSkin(SkinManager.getSkin(current), true);
        FileUtil.deleteDirectory(new File(SkinConst.SKIN_DIR + SkinConst.FILE_SEP + name));
      }
    }
  }
  
  public void addSkin()
  {
    this.menu.getModel().setSelected(false);
    this.menu.setPopupMenuVisible(false);
    JFileChooser chooser = new JFileChooser();
    String filterDes = "图像文件(*.bmp;*.jpg;*.jpeg;*.png)";
    FileNameExtensionFilter filter = new FileNameExtensionFilter(filterDes, new String[] { "bmp", "jpg", "jpeg", "png" });
    chooser.setApproveButtonMnemonic('O');
    chooser.setApproveButtonText("打开(O)");
    chooser.setCurrentDirectory(this.currentDir);
    chooser.setFileFilter(filter);
    chooser.setAcceptAllFileFilterUsed(false);
    int ret = chooser.showOpenDialog(SkinManager.getOwner());
    if (ret == 0)
    {
      File file = chooser.getSelectedFile();
      this.currentDir = file.getParentFile();
      String name = file.getName();
      int lastDotIndex = name.lastIndexOf('.');
      name = lastDotIndex > 0 ? name.substring(0, lastDotIndex) : name;
      if (SkinManager.getSkin(name) != null)
      {
        String title = "添加皮肤";
        String message = "皮肤“" + name + "”已经存在，是否替换？";
        JCMessageBox confirm = JCMessageBox.createQuestionMessageBox(SkinManager.getOwner(), title, message);
        if (confirm.open() != 4) {
          return;
        }
      }
      try
      {
        BufferedImage image = ImageIO.read(file);
        BufferedImage blurImage = UIUtil.createEdgeBlurryImage(image, 30, CRootPaneUI.BLUR_FILTER, null);
        BufferedImage previewImage = createPreviewImage(image);
        Skin skin = new Skin(name);
        String skinDirPath = SkinConst.SKIN_DIR + SkinConst.FILE_SEP + name;
        File skinDir = new File(skinDirPath);
        if (!skinDir.exists()) {
          skinDir.mkdirs();
        }
        ImageIO.write(image, "png", new File(skinDirPath + SkinConst.FILE_SEP + "normal.png"));
        ImageIO.write(blurImage, "png", new File(skinDirPath + SkinConst.FILE_SEP + "blur.png"));
        ImageIO.write(previewImage, "png", new File(skinDirPath + SkinConst.FILE_SEP + "preview.png"));
        SkinManager.getAllSkins().put(skin.getName().toUpperCase(), skin);
        this.menu.resetSkins();
        SkinManager.changeSkin(skin, true);
        image = null;
        blurImage = null;
        previewImage = null;
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
    }
  }
  
  private BufferedImage createPreviewImage(BufferedImage image)
  {
    BufferedImage previewImage = UIUtil.getGraphicsConfiguration(null).createCompatibleImage(30, 41, 3);
    Graphics2D g2d = previewImage.createGraphics();
    g2d.drawImage(image, 0, 0, previewImage.getWidth(), previewImage.getHeight(), null);
    g2d.dispose();
    return previewImage;
  }
  
  public boolean needChange(Point point, Container source)
  {
    int x = point.x + source.getX();
    int y = point.y + source.getY();
    while (!(source instanceof SkinUnit))
    {
      source = source.getParent();
      x += source.getX();
      y += source.getY();
    }
    return !this.menu.getSkinListBounds().contains(x, y);
  }
  
  public void mouseReleased(MouseEvent e)
  {
    Object source = e.getSource();
    if ((source instanceof JComponent))
    {
      JComponent c = (JComponent)source;
      Object eventKey = c.getClientProperty("EventKey");
      if (eventKey.equals("SkinAlphaChanged")) {
        SkinManager.savePropertie("Skin_Alpha", String.valueOf(SkinManager.getOwner().getImageAlpha()));
      } else if ((eventKey.equals("WinAlphaChanged")) && (UIUtil.isTranslucencySupported())) {
        SkinManager.savePropertie("Win_Alpha", String.valueOf(AWTUtilities.getWindowOpacity(SkinManager.getOwner())));
      }
    }
  }
  
  public void mouseEntered(MouseEvent e)
  {
    Object source = e.getSource();
    if ((source instanceof JComponent))
    {
      JComponent c = (JComponent)source;
      Object eventKey = c.getClientProperty("EventKey");
      if (eventKey.equals("SkinModePreview")) {
        this.menu.modePreview((Image)c.getClientProperty("BigImage"), false);
      }
    }
  }
  
  public void mouseExited(MouseEvent e)
  {
    Object source = e.getSource();
    if ((source instanceof JComponent))
    {
      JComponent c = (JComponent)source;
      Object eventKey = c.getClientProperty("EventKey");
      if (eventKey.equals("SkinModePreview")) {
        this.menu.modePreview((Image)c.getClientProperty("BigImage"), true);
      }
    }
  }
  
  public void stateChanged(ChangeEvent e)
  {
    Object source = e.getSource();
    if ((source instanceof JComponent))
    {
      JComponent c = (JComponent)source;
      Object eventKey = c.getClientProperty("EventKey");
      if (eventKey.equals("SkinAlphaChanged"))
      {
        float alpha = ((JCSlider)c).getValue() / 100.0F;
        for (Window win : Window.getWindows()) {
          if (win.isDisplayable()) {
            if ((win instanceof JCFrame)) {
              ((JCFrame)win).setImageAlpha(alpha);
            } else if ((win instanceof JCDialog)) {
              ((JCDialog)win).setImageAlpha(alpha);
            }
          }
        }
      }
      else if ((eventKey.equals("WinAlphaChanged")) && (UIUtil.isTranslucencySupported()))
      {
        float alpha = ((JCSlider)c).getValue() / 100.0F;
        for (Window win : Window.getWindows()) {
          if ((win.isDisplayable()) && (((win instanceof JFrame)) || ((win instanceof JDialog)))) {
            AWTUtilities.setWindowOpacity(win, alpha);
          }
        }
      }
    }
  }
  
  public void actionPerformed(ActionEvent e)
  {
    Object source = e.getSource();
    if ((source instanceof JComponent))
    {
      JComponent c = (JComponent)source;
      Object eventKey = c.getClientProperty("EventKey");
      if ((eventKey.equals("SkinModePreview")) && (((JCToggleButton)c).isSelected()))
      {
        SkinManager.getOwner().setImageDisplayMode((CRootPaneUI.ImageDisplayMode)c.getClientProperty("SkinModeValue"));
        SkinManager.savePropertie("Skin_Mode", String.valueOf(SkinManager.getOwner().getImageDisplayMode()));
      }
      else if (eventKey.equals("DelSkinOK"))
      {
        removeSkin(((DeleteConfirmPane)c.getParent()).getSkin(), false);
        this.menu.showPane(true, null);
      }
      else if (eventKey.equals("DelSkinCancel"))
      {
        this.menu.showPane(true, null);
      }
    }
  }
  
  public void popupMenuWillBecomeVisible(PopupMenuEvent e)
  {
    this.menu.showPane(true, null);
  }
  
  public void mouseClicked(MouseEvent e) {}
  
  public void mousePressed(MouseEvent e) {}
  
  public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {}
  
  public void popupMenuCanceled(PopupMenuEvent e) {}
}
